#include <QtCore/QtEndian>
#include "log_encoder.h"
#include "log_encoder_p.h"
#include "global.h"

namespace smsbilling {

static LogEncoder *log_encoder_instance = 0;

LogEncoderPrivate::LogEncoderPrivate() :
  log_manager(new smslog::LogManager(LOG_FILE_PATH, APP_NAME)) {

}

LogEncoderPrivate::~LogEncoderPrivate() {
  if(log_manager) {
    delete log_manager;
    log_manager = 0;
  }
}

QByteArray LogEncoderPrivate::encode(const QHash<int, QVariant> &p) const {
  QByteArray ba;
  for(QHash<int, QVariant>::const_iterator i = p.constBegin();
      i != p.constEnd();
      i++) {
    ba += encode(i.key()) + encode(i.value());
  }
  return ba;
}

QByteArray LogEncoderPrivate::encode(const QVariant &v) const {
  switch(v.type()) {
    case QVariant::Bool:
      return encode(v.toBool());
    case QVariant::Char:
      return encode(v.toChar().toLatin1());
    case QVariant::Int:
      return encode(v.toInt());
    case QVariant::UInt:
      return encode(v.toUInt());
    case QVariant::String:
      return encode(v.toString());
    case QVariant::ByteArray: {
      QByteArray ba(v.toByteArray());
      ba.prepend(encode(ba.size()));
      return ba;
    }
    default:
      return QByteArray();
  }
}

QByteArray LogEncoderPrivate::encode(bool p) const {
  if(p) {
    return QByteArray(1, 0x01);
  } else {
    return QByteArray(1, 0x00);
  }
}

QByteArray LogEncoderPrivate::encode(char p) const {
  return QByteArray(1, p);
}

QByteArray LogEncoderPrivate::encode(int p) const {
  p = qToBigEndian(p);
  char *c_pt(reinterpret_cast<char *>(&p));
  QByteArray ba(4, 0x00);
  ba[0] = *(c_pt++);
  ba[1] = *(c_pt++);
  ba[2] = *(c_pt++);
  ba[3] = *c_pt;
  return ba;
}

QByteArray LogEncoderPrivate::encode(uint p) const {
  p = qToBigEndian(p);
  char *c_pt(reinterpret_cast<char *>(&p));
  QByteArray ba(4, 0x00);
  ba[0] = *(c_pt++);
  ba[1] = *(c_pt++);
  ba[2] = *(c_pt++);
  ba[3] = *c_pt;
  return ba;
}

QByteArray LogEncoderPrivate::encode(const QString &p) const {
  return p.toUtf8() + QByteArray(1, '\0');
}

LogEncoder::LogEncoder() : p(new LogEncoderPrivate) {
  log_encoder_instance = this;
}

LogEncoder::~LogEncoder() {
  log_encoder_instance = 0;
  if(p) {
    delete p;
    p = 0;
  }
}

LogEncoder *LogEncoder::instance() {
  return log_encoder_instance;
}

void LogEncoder::encode(smslog::LogLevel log_level,
                        int cls,
                        int obj,
                        int code_message,
                        const LogMsgParams &parameters) const {
  QByteArray msg(p->encode(code_message) + p->encode(parameters));

  switch(log_level) {
    case smslog::DEBUG:
      p->log_manager->debug(logapp::SMS_ROUTER, cls, obj, msg);
      break;
    case smslog::INFO:
      p->log_manager->info(logapp::SMS_ROUTER, cls, obj, msg);
      break;
    case smslog::WARNING:
      p->log_manager->warning(logapp::SMS_ROUTER, cls, obj, msg);
      break;
    case smslog::ERROR:
      p->log_manager->error(logapp::SMS_ROUTER, cls, obj, msg);
      break;
    case smslog::FATAL:
      p->log_manager->fatal(logapp::SMS_ROUTER, cls, obj, msg);
      break;
  }
}

} // namespace smsbilling
